package com.uduemc.biso.node.web.service.impl;

import java.io.IOException;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uduemc.biso.core.extities.center.Host;
import com.uduemc.biso.core.extities.center.Site;
import com.uduemc.biso.core.extities.center.SysSystemType;
import com.uduemc.biso.core.utils.CryptoJava;
import com.uduemc.biso.node.core.common.entities.FormData;
import com.uduemc.biso.node.core.common.entities.HostInfos;
import com.uduemc.biso.node.core.common.entities.Navigation;
import com.uduemc.biso.node.core.common.entities.SiteBasic;
import com.uduemc.biso.node.core.common.entities.SiteComponent;
import com.uduemc.biso.node.core.common.entities.SiteComponentSimple;
import com.uduemc.biso.node.core.common.entities.SiteContainer;
import com.uduemc.biso.node.core.common.entities.SitePage;
import com.uduemc.biso.node.core.common.entities.sitebasic.AccessDevice;
import com.uduemc.biso.node.core.common.entities.sitepage.PageType;
import com.uduemc.biso.node.core.common.entities.surfacedata.BannerData;
import com.uduemc.biso.node.core.common.entities.surfacedata.MainData;
import com.uduemc.biso.node.core.common.entities.surfacedata.bannerdata.Banner;
import com.uduemc.biso.node.core.common.entities.surfacedata.maindata.Logo;
import com.uduemc.biso.node.core.entities.HConfig;
import com.uduemc.biso.node.core.entities.SConfig;
import com.uduemc.biso.node.core.entities.SContainerQuoteForm;
import com.uduemc.biso.node.core.entities.SPage;
import com.uduemc.biso.node.core.entities.SSystem;
import com.uduemc.biso.node.web.component.RequestHolder;
import com.uduemc.biso.node.web.config.SpringContextUtil;
import com.uduemc.biso.node.web.entities.SiteSurfaceData;
import com.uduemc.biso.node.web.service.SurfaceDataEncodeCacheService;
import com.uduemc.biso.node.web.service.SurfaceService;
import com.uduemc.biso.node.web.service.byfeign.BannerService;
import com.uduemc.biso.node.web.service.byfeign.ComponentService;
import com.uduemc.biso.node.web.service.byfeign.ContainerService;
import com.uduemc.biso.node.web.service.byfeign.FormService;
import com.uduemc.biso.node.web.service.byfeign.HostService;
import com.uduemc.biso.node.web.service.byfeign.LanguageService;
import com.uduemc.biso.node.web.service.byfeign.LogoService;
import com.uduemc.biso.node.web.service.byfeign.NavigationService;
import com.uduemc.biso.node.web.service.byfeign.PageService;
import com.uduemc.biso.node.web.service.byfeign.SiteConfigService;
import com.uduemc.biso.node.web.service.byfeign.SiteService;
import com.uduemc.biso.node.web.service.byfeign.SysStaticDataService;
import com.uduemc.biso.node.web.utils.DeviceUtils;

import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class SurfaceServiceImpl implements SurfaceService {

	@Autowired
	private RequestHolder requestHolder;

	@Autowired
	private BannerService bannerServiceImpl;

	@Autowired
	private LogoService logoServiceImpl;

	@Autowired
	private FormService formServiceImpl;

	@Autowired
	private NavigationService navigationServiceImpl;

	@Autowired
	private ObjectMapper objectMapper;

	@Autowired
	private SiteService siteServiceImpl;

	@Autowired
	private SiteConfigService siteConfigServiceImpl;

	@Autowired
	private HostService hostServiceImpl;

	@Autowired
	private SurfaceDataEncodeCacheService surfaceDataEncodeCacheServiceImpl;

	@Autowired
	private SpringContextUtil springContextUtil;

	@Autowired
	private HttpServletRequest request;

	@Autowired
	private SysStaticDataService sysStaticDataServiceImpl;

	@Autowired
	private LanguageService languageServiceImpl;

	@Autowired
	private ContainerService containerServiceImpl;

	@Autowired
	private ComponentService componentServiceImpl;

	@Autowired
	private PageService pageServiceImpl;

	@Override
	public String surface(long hostId, long siteId, long pageId, String pfx, String pfxhf)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		SiteSurfaceData siteSurfaceData = surfaceDataEncodeCacheServiceImpl.cacheGet(siteId, pageId);
		if (siteSurfaceData == null || !springContextUtil.prod()) {
			// 整体页面数据部分构建
			siteSurfaceData = getSiteSurfaceData(hostId, siteId, pageId, requestHolder.getAccessHost().getUri());
			surfaceDataEncodeCacheServiceImpl.cacheSet(siteId, pageId, siteSurfaceData);
		}

		return surfaceDataEncode(siteSurfaceData, pfx, pfxhf);
	}

	@Override
	public String surface(long hostId, long siteId, String pfx, String pfxhf)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		long pageId = 0;
		SiteSurfaceData siteSurfaceData = getSiteSurfaceData(hostId, siteId, pageId, requestHolder.getAccessHost().getUri());
		return surfaceDataEncode(siteSurfaceData, pfx, pfxhf);
	}

	private String surfaceDataEncode(SiteSurfaceData siteSurfaceData, String pfx, String pfxhf) {
		if (siteSurfaceData == null) {
			return "/* 获取的 SiteSurfaceData 数据为空！ */";
		}

		if (DeviceUtils.isMobileDevice(request)) {
			siteSurfaceData.setDevice(2);
		} else {
			siteSurfaceData.setDevice(1);
		}

		siteSurfaceData.setPrefix(pfx);
		siteSurfaceData.setPrefixHref(pfxhf);
		String surfaceDataEncode = "";
		try {
			surfaceDataEncode = CryptoJava.en(objectMapper.writeValueAsString(siteSurfaceData));
		} catch (Exception e) {
		}

		if (StrUtil.isBlank(surfaceDataEncode)) {
			return "/* 对 SiteSurfaceData 数据加密失败！ */";
		}

		return "(function(window,$){$.surfaceDataEncode = \"" + surfaceDataEncode + "\"})(window,jQuery)";
	}

	@Override
	public SiteSurfaceData getSiteSurfaceData(long hostId, long siteId, long pageId, String siteUri)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		HostInfos hostInfos = hostServiceImpl.getHostInfosByHostId(hostId);
		if (hostInfos == null) {
			log.warn("未获取到有效的 hostInfos 数据！");
			return null;
		}
		Host host = hostInfos.getHost();
		HConfig hostConfig = hostInfos.getHostConfig();
		List<Site> listSite = hostInfos.getListSite();
		if (host == null) {
			log.warn("未获取到有效的 host 数据！");
			return null;
		}
		Site site = siteServiceImpl.findByHostIdAndId(siteId, hostId);
		if (site == null) {
			log.warn("未获取到有效的 site 数据！");
			return null;
		}

		SConfig sConfig = siteConfigServiceImpl.getInfoBySiteId(hostId, siteId);

		SiteBasic siteBasic = getSiteBasic(hostId, siteId, siteUri);

		SitePage sitePage = getSitePage(hostId, pageId);

		SiteSurfaceData siteSurfaceData = SiteSurfaceData.getSiteSurfaceData(host, site, siteBasic, sitePage);

		siteSurfaceData.setHConfig(hostConfig);
		if (sConfig.getMenuConfig() == null) {
			sConfig.setMenuConfig("");
		}
		siteSurfaceData.setSConfig(sConfig);

		// 获取 language 数据
		siteSurfaceData.setLanguage(languageServiceImpl.getLanguageBySite(site));

		// 设置所有的可用站点数据
		siteSurfaceData.setSites(listSite);

		// 设置所有的语言数据
		siteSurfaceData.setLanguages(languageServiceImpl.getAll());

		// 设置是否为 debug
		siteSurfaceData.setDebug(springContextUtil.prod() ? false : true);

		// 设置 SysContainerType 数据
		siteSurfaceData.setSysContainerTypeList(sysStaticDataServiceImpl.getContainerTypeInfos());

		// 设置 SysComponentType 数据
		siteSurfaceData.setSysComponentTypeList(sysStaticDataServiceImpl.getComponentTypeInfos());

		siteSurfaceData.setMain(getMainData(hostId, siteId, sitePage != null && sitePage.getSPage() != null ? sitePage.getSPage() : null));

		return siteSurfaceData;
	}

	@Override
	public SiteBasic getSiteBasic(long hostId, long siteId, String siteUri) {
		// 获取 hostId、siteId、siteUri 基础信息
		SiteBasic siteBasic = null;
		try {
			// 通过传递的参数进行识别获取当前设备
			AccessDevice device = null;
			if (request.getParameter("device") == null) {
				device = AccessDevice.PC;
			} else {
				if (request.getParameter("device").toLowerCase().equals("pc")) {
					device = AccessDevice.PC;
				} else if (request.getParameter("device").toLowerCase().equals("mp")) {
					device = AccessDevice.MP;
				} else if (request.getParameter("device").toLowerCase().equals("pad")) {
					device = AccessDevice.PAD;
				}
			}
			siteBasic = SiteBasic.getSiteBasic(hostId, siteId, device, siteUri);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return siteBasic;
	}

	@Override
	public SitePage getSitePage(long hostId, long pageId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		if (pageId < 1) {
			return null;
		}
		SitePage sitePage = pageServiceImpl.getSitePageByHostPageId(hostId, pageId);
		if (sitePage == null) {
			return null;
		}
		SPage sPage = sitePage.getSPage();
		SSystem sSystem = sitePage.getSSystem();
		if (sPage == null) {
			return null;
		}

		Short type = sPage.getType();
		boolean bootPage = type.shortValue() == (short) 0 ? true : false;
		if (bootPage) {
			sitePage.setType(PageType.CUSTOM);
			sitePage.setTemplateName("index");
		} else {
			// 非引导页的情况
			if (sitePage.boolCustom()) {
				sitePage.setType(PageType.CUSTOM);
				sitePage.setTemplateName("index");
			} else {
				// 系统页面
				String templateName = "";
				sitePage.setType(PageType.LIST);
				List<SysSystemType> systemTypeInfos = sysStaticDataServiceImpl.getSystemTypeInfos();
				for (SysSystemType sysSystemType : systemTypeInfos) {
					if (sysSystemType.getId() != null && sysSystemType.getId().longValue() == sSystem.getId().longValue()) {
						templateName = sysSystemType.getListType();
					}
				}
				sitePage.setTemplateName(templateName);
			}
		}
		return sitePage;
	}

	@Override
	public MainData getMainData(long hostId, long siteId, SPage sPage) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		Long pageId = sPage == null ? 0 : sPage.getId();

		MainData mainData = new MainData();

		// 获取 logo 数据
		mainData.setLogo(getLogo(hostId, siteId));

		// 获取 banner 数据
		mainData.setBanner(getBanner(hostId, siteId, pageId));

		// 获取 navigation 数
		mainData.setListNavigation(getNavigation(hostId, siteId));

		// 页面主体区域的容器数据
		mainData.setContainerMain(getContainerMain(hostId, siteId, sPage));

		// 页面底部区域的容器数据
		mainData.setContainerFooter(getContainerFooter(hostId, siteId));

		// 页面头部区域的容器数据
		mainData.setContainerHeader(getContainerHeader(hostId, siteId));

		// 页面Banner区域的容器数据
		mainData.setContainerBanner(getContainerBanner(hostId, siteId));

		// 页面区域（type=4）容器数据
//		mainData.setContainerSite(getCurrentContainerSite());

		// 页面主体区域的组件数据
		mainData.setComponentMain(getComponentMain(hostId, siteId, sPage));

		// 页面底部区域的组件数据
		mainData.setComponentFooter(getComponentFooter(hostId, siteId));

		// 页面头部区域的组件数据
		mainData.setComponentHeader(getComponentHeader(hostId, siteId));

		// 页面Banner区域的组件数据
		mainData.setComponentBanner(getComponentBanner(hostId, siteId));

		// 未定义（type = 4）区域的组件数据
//		mainData.setComponentSite(getCurrentComponentSite());

		// 简易站点组件区域，需要条件过滤status为0-正常情况下的数据
		mainData.setSiteComponentSimple(getSiteComponentSimple(hostId, siteId));

		// 简易整站组件区域，需要条件过滤status为0-正常情况下的数据
		mainData.setHostComponentSimple(getHostComponentSimple(hostId));

		// 通过 hostId、siteId 获取 SForm 以及其 container、component 对应的数据列表
		mainData.setFormData(getFormData(hostId, siteId));

		// 通过 hostId、siteId 获取 SContainerQuoteForm 对应的数据列表
		mainData.setContainerQuoteForm(getContainerQuoteForm(hostId, siteId));

		return mainData;
	}

	@Override
	public Logo getLogo(long hostId, long siteId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		Logo logo = logoServiceImpl.getSiteLogoByHostSiteId(hostId, siteId);
		return logo;
	}

	@Override
	public BannerData getBanner(long hostId, long siteId, long pageId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		BannerData bannerData = new BannerData();
		if (pageId < 1) {
			return bannerData;
		}
		Banner pc = bannerServiceImpl.getBannerByHostSitePageIdEquip(hostId, siteId, pageId, (short) 1);
		Banner wap = bannerServiceImpl.getBannerByHostSitePageIdEquip(hostId, siteId, pageId, (short) 2);

		bannerData.setPc(pc);
		bannerData.setPhone(wap);

		return bannerData;
	}

	@Override
	public List<Navigation> getNavigation(long hostId, long siteId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		List<Navigation> data = navigationServiceImpl.getInfosByHostSiteId(hostId, siteId);
		return data;
	}

	@Override
	public List<SiteContainer> getContainerMain(long hostId, long siteId, SPage sPage)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		if (sPage == null) {
			return null;
		}
		if (sPage.getType().shortValue() == (short) 0) {
			// 引导页主体内容数据
			return containerServiceImpl.getInfosByHostSitePageIdAndArea(hostId, 0L, sPage.getId(), (short) 0);
		} else if (sPage.getType().shortValue() == (short) 1) {
			// 普通页面主体内容数据
			return containerServiceImpl.getInfosByHostSitePageIdAndArea(hostId, siteId, sPage.getId(), (short) 0);
		}
		return null;
	}

	@Override
	public List<SiteContainer> getContainerFooter(long hostId, long siteId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		return containerServiceImpl.getInfosByHostSitePageIdAndArea(hostId, siteId, 0L, (short) 1);
	}

	@Override
	public List<SiteContainer> getContainerHeader(long hostId, long siteId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		return containerServiceImpl.getInfosByHostSitePageIdAndArea(hostId, siteId, 0L, (short) 2);
	}

	@Override
	public List<SiteContainer> getContainerBanner(long hostId, long siteId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		return containerServiceImpl.getInfosByHostSitePageIdAndArea(hostId, siteId, 0L, (short) 3);
	}

	@Override
	public List<SiteComponent> getComponentMain(long hostId, long siteId, SPage sPage)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		if (sPage == null) {
			return null;
		}
		if (sPage.getType().shortValue() == (short) 0) {
			// 引导页主体内容数据
			return componentServiceImpl.getInfosByHostSitePageIdAndArea(hostId, 0L, sPage.getId(), (short) 0);
		} else {
			// 普通页面主体内容数据
			return componentServiceImpl.getInfosByHostSitePageIdAndArea(hostId, siteId, sPage.getId(), (short) 0);
		}
	}

	@Override
	public List<SiteComponent> getComponentFooter(long hostId, long siteId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		return componentServiceImpl.getInfosByHostSitePageIdAndArea(hostId, siteId, 0L, (short) 1);
	}

	@Override
	public List<SiteComponent> getComponentHeader(long hostId, long siteId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		return componentServiceImpl.getInfosByHostSitePageIdAndArea(hostId, siteId, 0L, (short) 2);
	}

	@Override
	public List<SiteComponent> getComponentBanner(long hostId, long siteId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		return componentServiceImpl.getInfosByHostSitePageIdAndArea(hostId, siteId, 0L, (short) 3);
	}

	@Override
	public List<SiteComponentSimple> getSiteComponentSimple(long hostId, long siteId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		List<SiteComponentSimple> componentSimpleInfo = componentServiceImpl.getComponentSimpleInfo(hostId, siteId, (short) -1,
				"`s_component_simple`.`type_id` ASC");
		return componentSimpleInfo;
	}

	@Override
	public List<SiteComponentSimple> getHostComponentSimple(long hostId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		List<SiteComponentSimple> componentSimpleInfo = componentServiceImpl.getComponentSimpleInfo(hostId, 0L, (short) -1,
				"`s_component_simple`.`type_id` ASC");
		return componentSimpleInfo;
	}

	@Override
	public List<FormData> getFormData(long hostId, long siteId) throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		List<FormData> data = formServiceImpl.findInfosByHostSiteId(hostId, siteId);
		return data;
	}

	@Override
	public List<SContainerQuoteForm> getContainerQuoteForm(long hostId, long siteId)
			throws JsonParseException, JsonMappingException, JsonProcessingException, IOException {
		List<SContainerQuoteForm> listSContainerQuoteForm = containerServiceImpl.getContainerQuoteForm(hostId, siteId, (short) 0);
		return listSContainerQuoteForm;
	}

}
